/***
 * @Description: 本文件主要是对定时器相关的内容进行构建，包括数据结构的定义和函数调用接口的C语言文件
 * @Author: Liverpool
 * @Date: 2024-05-27 23:15:41
 * @LastEditTime: 2024-05-27 23:16:48
 * @LastEditors: Liverpool
 */

#include "timer.h"
#include "debug.h"
#include "list.h"

static D_List timer_list; // 定时器链表(递增有序排列)
#if Debug_Display_Enable(Debug_Timer)
static void display_timer_list(void)
{
    plat_printf("-----------------------timer list------------------------\n");
    D_ListNode *node;
    int index = 0;
    list_for_each_node(node, &timer_list)
    {
        D_Net_timer *timer = list_entry(node, D_Net_timer, node);
        plat_printf("%d: %s, period=%d, curr=%d, reload=%d\n", index++, timer->name, timer->flags & NET_TIMER_RELOAD ? 1 : 0, timer->curr, timer->reload);
    }
    plat_printf("-------------------timer list end------------------------\n");
}
#else
#define display_timer_list()
#endif

/***
 * @description: 定时器模块的初始化
 * @Author: Liverpool
 * @Date: 2024-05-28 00:12:52
 * @return {*} 初始化过程中产生的错误
 */
net_err_t net_timer_init(void)
{
    debug_info(Debug_Timer, "timer init");

    list_init(&timer_list); // 对定时器链表进行初始化

    debug_info(Debug_Timer, "timer init done...");
    return NET_ERR_OK;
}

/***
 * @description: (静态函数)在递增的定时器链表中插入一个新的定时器
 * @Author: Liverpool
 * @Date: 2024-06-01 16:40:15
 * @return {*}
 * @param {D_Net_timer} *insert_timer 需要插入新的定时器
 */
static void insert_timer(D_Net_timer *insert_timer)
{
    D_ListNode *node;
    D_ListNode *pre = (D_ListNode *)0;
    list_for_each_node(node, &timer_list) // 对整个定时器链表进行遍历
    {
        D_Net_timer *curr = list_entry(node, D_Net_timer, node);
        if (insert_timer->curr > curr->curr) // 如果现在的定时器的时间小于插入的定时器的时间
        {
            insert_timer->curr -= curr->curr;
        }
        else if (insert_timer->curr == curr->curr) // 当前定时器的时间等于新插入的定时器的时间
        {
            insert_timer->curr = 0;
            list_insert_after(&timer_list, node, &insert_timer->node);
            return;
        }
        else // 当前定时器的时间大于新插入的定时器的时间
        {
            curr->curr -= insert_timer->curr;
            if (pre) //
            {
                list_insert_after(&timer_list, pre, &insert_timer->node);
            }
            else // 没有找到当前节点前结点(链表的首结点)
            {
                list_insert_first(&timer_list, &insert_timer->node);
            }
            return;
        }
        pre = node;
    }
    list_insert_last(&timer_list, &insert_timer->node);
}

/***
 * @description: 在定时器链表中添加新的定时器
 * @Author: Liverpool
 * @Date: 2024-05-29 00:39:56
 * @return {*}   在添加过程中出现的错误
 * @param {D_Net_timer} *timer 添加的定时器的内存地址
 * @param {char} *name 定时器的名字
 * @param {time_proc_func} func 定时器的回调函数
 * @param {void} *arg 回调函数所需要使用的参数
 * @param {int} ms 定时器的周期值
 * @param {int} flags 定时器所特定的标志位
 */
net_err_t net_timer_add(D_Net_timer *timer, const char *name, time_proc_func func, void *arg, int ms, int flags)
{
    debug_info(Debug_Timer, "insert timer:%s", name);
    // 对定时器参数进行赋值
    plat_strncpy(timer->name, name, TIMER_NAME_SIZE);
    timer->name[TIMER_NAME_SIZE - 1] = '\0';
    timer->curr = ms;
    timer->reload = ms;
    timer->proc = func;
    timer->arg = arg;
    timer->flags = flags;
    insert_timer(timer);
    display_timer_list();
    return NET_ERR_OK;
}

/***
 * @description: 在定时器链表中删除对应的定时器
 * @Author: Liverpool
 * @Date: 2024-06-01 23:41:25
 * @return {*}
 * @param {D_Net_timer} *timer 需要删除的定时器的内存地址
 */
void net_timer_remove(D_Net_timer *timer)
{
    debug_info(Debug_Timer, "remove timer:%s", timer->name);
    D_ListNode *node;
    list_for_each_node(node, &timer_list)
    {
        // 找到定时器链表中的对应定时器
        D_Net_timer *curr = list_entry(node, D_Net_timer, node);
        if (curr != timer)
        {
            continue; // 如果不是需要查找的定时器，那就继续寻找
        }
        D_ListNode *next = list_node_get_next(&timer->node);
        if (next) // 如果该节点后面有后续的定时器节点，需要增加当前节点的定时器计数值
        {
            D_Net_timer *next_timer = list_entry(next, D_Net_timer, node);
            next_timer->curr += curr->curr;
        }
        list_remove_node(&timer_list, &timer->node);
    }
    display_timer_list();
}

/***
 * @description: 对定时器链表进行扫描
 * @Author: Liverpool
 * @Date: 2024-06-02 09:30:31
 * @return {*} 在扫描过程中的错误
 * @param {int} time_diff 与上次进行定时器扫描的时间间隔(ms)
 */
net_err_t net_timer_check_tmo(int time_diff)
{
    // 等待处理的定时器链表
    D_List wait_list;
    list_init(&wait_list);

    D_ListNode *node = list_get_first(&timer_list);
    while (node) // 对定时器链表进行遍历
    {
        D_ListNode *next = list_node_get_next(node);
        D_Net_timer *timer = list_entry(node, D_Net_timer, node);
        if (timer->curr > time_diff)
        {
            // 如果当前节点的计数值已经大于间隔值，那就需要结束对链表的遍历
            timer->curr -= time_diff;
            break;
        }
        time_diff -= timer->curr;
        // 当前的节点计数值<=时间间隔
        timer->curr = 0;
        list_remove_node(&timer_list, &timer->node); // 在定时器链表中移除当前节点
        list_insert_last(&wait_list, &timer->node);  // 在等待链表中插入需要执行定时器回调函数的定时器节点
        node = next;
    }
    // 对等待列表的定时器的回调函数进行处理
    while ((node = list_remove_first(&wait_list)) != (D_ListNode *)0)
    {
        D_Net_timer *timer = list_entry(node, D_Net_timer, node);
        timer->proc(timer, timer->arg);      // 定时器回调函数
        if (timer->flags & NET_TIMER_RELOAD) // 如果是周期定时器，需要重新插入到定时器链表中
        {
            timer->curr = timer->reload;
            insert_timer(timer);
        }
    }
    display_timer_list();
    return NET_ERR_OK;
}

/***
 * @description: 返回第一个定时器节点的计数值
 * @Author: Liverpool
 * @Date: 2024-06-02 19:03:34
 * @return {*} 返回定时器的计数值
 */
int net_timer_first_tmo(void)
{
    D_ListNode *node = list_get_first(&timer_list);
    if (node)
    {
        D_Net_timer *timer = list_entry(node, D_Net_timer, node);
        return timer->curr;
    }
    return 0;
}